module Schaefer
	class Interpreter
		attr_accessor :base_environment, :current_environment, :parser

		def initialize()
			@base_environment = @current_environment = Schaefer::Environment.new 
      @parser = Parser.new
      loadLibrary
		end

		def run(program)
 			expressions = @parser.parse(program)
			result = nil
			expressions.each do |expression|
				result = evaluate(expression)
			end
			return result
		end

		def evaluate(expression)
			return @current_environment.find(expression) if expression.is_a? Symbol
			return expression unless expression.is_a? Array

			if expression[0] == :define
				return @current_environment.define(expression[1], evaluate(expression[2]))
			elsif expression[0] == :native_function
				return eval(expression[1])
			else
				function = evaluate(expression[0])
				raise RuntimeError, "\n#{expression[0]} is not a function" unless function.is_a? Proc
        arguments = expression.slice(1, expression.length)
				return function.call(arguments, self)
			end
		end

    private

    def loadLibrary
      pattern = File.join(File.dirname(__FILE__), "Library", "*", "*.sch")
      Dir[pattern].each do |item|
        File.open(item) do |file|
          run(file.read)
        end
      end
    end
	end
end
